package com.googlecode.lookie.swing.laf;

import java.util.HashSet;
import java.util.Set;

import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AbstractLookAndFeelConfigurer
    implements LookAndFeelConfigurer
{

    private static final Logger logger = LoggerFactory.getLogger( AbstractLookAndFeelConfigurer.class );

    private Set<LookAndFeelConfigurerListener> listeners = new HashSet<LookAndFeelConfigurerListener>();

    private LookAndFeelDescriptor currentDescriptor;

    /* (non-Javadoc)
     * @see com.googlecode.lookie.swing.laf.LookAndFeelConfigurer#getCurrentDescriptor()
     */
    public LookAndFeelDescriptor getCurrentDescriptor()
    {
        return currentDescriptor;
    }

    /* (non-Javadoc)
     * @see com.googlecode.lookie.swing.laf.LookAndFeelConfigurer#createDefaultTreeCellRenderer()
     */
    public TreeCellRenderer createDefaultTreeCellRenderer()
    {
        String className = currentDescriptor.getTreeCellRendererClassName();
        TreeCellRenderer renderer = null;
        if ( className != null )
        {
            renderer = (TreeCellRenderer) Utils.instantiate( className, TreeCellRenderer.class );
        }
        if ( renderer == null )
        {
            renderer = new DefaultTreeCellRenderer();
        }
        return renderer;
    }

    /* (non-Javadoc)
     * @see com.googlecode.lookie.swing.laf.LookAndFeelConfigurer#addListener(com.googlecode.lookie.swing.laf.LookAndFeelConfigurerListener)
     */
    public void addListener( LookAndFeelConfigurerListener listener )
    {
        listeners.add( listener );
    }

    /* (non-Javadoc)
     * @see com.googlecode.lookie.swing.laf.LookAndFeelConfigurer#removeListener(com.googlecode.lookie.swing.laf.LookAndFeelConfigurerListener)
     */
    public void removeListener( LookAndFeelConfigurerListener listener )
    {
        listeners.remove( listener );
    }

    /* (non-Javadoc)
     * @see com.googlecode.lookie.swing.laf.LookAndFeelConfigurer#configure(com.googlecode.lookie.swing.laf.LookAndFeelDescriptor)
     */
    public void configure( LookAndFeelDescriptor descriptor )
    {

        try
        {
            UIManager.setLookAndFeel( descriptor.getClassName() );
        }
        catch ( ClassNotFoundException e )
        {
            logger.warn( "error configuring look and feel", e );
        }
        catch ( InstantiationException e )
        {
            logger.warn( "error configuring look and feel", e );
        }
        catch ( IllegalAccessException e )
        {
            logger.warn( "error configuring look and feel", e );
        }
        catch ( UnsupportedLookAndFeelException e )
        {
            logger.warn( "error configuring look and feel", e );
        }

        // TODO mark the descriptor to indicate if something went wrong when
        // setting the look and feel

        currentDescriptor = descriptor;
    }

    /* (non-Javadoc)
     * @see com.googlecode.lookie.swing.laf.LookAndFeelConfigurer#configureAndUpdate(com.googlecode.lookie.swing.laf.LookAndFeelDescriptor)
     */
    public void configureAndUpdate( LookAndFeelDescriptor descriptor )
    {
        LookAndFeelDescriptor oldDescriptor = currentDescriptor;
        configure( descriptor );
        notifyListeners( oldDescriptor, currentDescriptor );
    }

    private void notifyListeners( LookAndFeelDescriptor oldDescriptor, LookAndFeelDescriptor newDescriptor )
    {
        for ( LookAndFeelConfigurerListener listener : listeners )
        {
            listener.update( oldDescriptor, newDescriptor );
        }
    }

}
